<?php

namespace app\admin\controller;

use app\admin\model\IdentityInfo;
use app\admin\model\TeacherClass;
use app\admin\model\TeacherSubscribe;
use app\common\controller\Backend;
use think\Config;
use think\Db;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\DbException;
use think\exception\PDOException;
use think\exception\ValidateException;

/**
 * 教师课程安排管理
 *
 * @icon fa fa-circle-o
 */
class TeacherClassDtl extends Backend
{

    /**
     * TeacherClassDtl模型对象
     * @var \app\admin\model\TeacherClassDtl
     */
    protected $model = null;

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\admin\model\TeacherClassDtl;
        $this->view->assign("statusList", $this->model->getStatusList());
        $this->view->assign("cycleList", $this->model->getCycleList());

        $this->assignconfig("statusList", $this->model->getStatusList());
        $this->assignconfig("cycleList", $this->model->getCycleList());
    }



    /**
     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
     */

    public function index()
    {
        //设置过滤方法
        $this->request->filter(['strip_tags', 'trim']);
        if (false === $this->request->isAjax()) {
            return $this->view->fetch();
        }
        //如果发送的来源是 Selectpage，则转发到 Selectpage
        if ($this->request->request('keyField')) {
            return $this->selectpage();
        }
        [$where, $sort, $order, $offset, $limit] = $this->buildparams();
        $param = $this->request->param();
        $dtl_where = ' 1=1';
        if(isset($param['class_id'])&&$param['class_id']){
            $dtl_where .= ' and teacher_class_id = '.$param['class_id'];
        }
        $list = $this->model
            ->where($where)
            ->where($dtl_where)
            ->order($sort, $order)
            ->paginate($limit);

        $result = ['total' => $list->total(), 'rows' => $list->items()];
        return json($result);
    }


    /**
     * 添加
     *
     * @return string
     * @throws \think\Exception
     */
    public function add()
    {
        if (false === $this->request->isPost()) {
            $params = $this->request->param();
//            $class = \app\admin\model\TeacherClass::where(['id'=>$params['class_id']])->find();

            $class = TeacherClass::where(['id'=>$params['class_id']])->find();
//            if($class['status'] != 1){
//                $this->error('已完成或已中止的课程不可新增课程安排');
//            }
            $week_arr = TeacherSubscribe::where(['teacher_id'=>$class['teacher_id']])->where('1=1 and class_id = 0')->column('week');
            $arr = [];
            foreach ($week_arr as $k=>$v){
                $arr[] = (int)$v;
            }
            sort($arr);
            $data['week'] = $arr;
            $identity_info_model = new \app\admin\model\IdentityInfo();
            $getWeekList = $identity_info_model->getWeekList();
            $week_name = [];
            foreach ($arr as $k=>$v){
                $week_name[$v] = $getWeekList[$v];
            }

            $this->view->assign("weekList", $week_name);
            $this->view->assign("period_set", $class['period_set']);
            $this->view->assign("row", $params);
            return $this->view->fetch();
        }
        $params = $this->request->post('row/a');
        if (empty($params)) {
            $this->error(__('Parameter %s can not be empty', ''));
        }
        $params = $this->preExcludeFields($params);

        if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
            $params[$this->dataLimitField] = $this->auth->id;
        }

        if(!isset($params['week_date'])||!$params['week_date']){
            $this->error('日/周必传');
        }
        $class = TeacherClass::where(['id'=>$params['teacher_class_id']])->find();
        $params['cycle'] = $class['period_set'];
        if($params['status'] == 2){
            //已完成的话 增加进度
            $class_num = $params['class_num'];
            $class_num_alls = precisionRestore($class_num,$class['completed_class_num'],'加法');
        }

        $identity_info = \app\admin\model\IdentityInfo::where(['user_id'=>$class['teacher_id'],'identity_type'=>'教师'])->with(['clubDtlS'])->find();
        if(!$identity_info){
            $this->error('教师不存在');
        }
        $td = \app\admin\model\TeacherDetail::where(['id'=>$class['teacher_detail_id']])->find();
        if(isset($td['course_duration'])&&$td['course_duration']){
            //当教师课程配置了课程时间 则赋值课程时间
            $duration = $td['course_duration'];
        }else{
            //如果没有配置，则取公共课程时间
            $defaultDuration = Config::get('course.default_course_duration', '');
            $duration = $defaultDuration;
        }
        $time = explode('-',$identity_info['appointment_time']);
        $week = explode(',',$identity_info['appointment_time_week']);
        $identity_info_model = new \app\admin\model\IdentityInfo();
        $week_list_name = $identity_info_model->getWeekNameList();
        $week_arr = [];
        foreach ($week as $k=>$v){
            $key = isset($week_list_name[$v]) ? $week_list_name[$v] : '';
            $week_arr[$k] = $key;
        }
        $weekday = $params['week_date'];//长期默认周 传过来的是数字
        //判断日期是否在可约范围内，判断上课时间，判断课时
        if($class['period_set'] == 2){
            //短期
            $inputDate = $params['week_date'];

            $weekday = date('N', strtotime($inputDate));
        }

        if (!in_array($weekday, $week_arr)) {
            $this->error('周'. \app\admin\model\TeacherClassDtl::numberToChinese($weekday).'不在可约时间');
        }
        if($params['class_num']>6){
            $this->error('单次上课最大6课时');
        }
        if(isset($time[0])&&$time[0]&&isset($time[1])&&$time[1]){
            $add_time = precisionRestore($params['class_num'],$duration,'乘法');
            $end_time = $this->safeTimeAdd($params['time_start'],$add_time);
            if(!$end_time){
                $this->error('课程开始时间加上课时不可跨天');
            }
            $result = $this->isTimeBetween($params['time_start'], $time[0], $time[1]);
            if($result == false){
                $this->error('课程开始时间不在服务时间内');
            }
            $result = $this->isTimeBetween($end_time, $time[0], $time[1]);
            if($result == false){
                $this->error('课程结束时间不在服务时间内');
            }
        }
        if($class['period_set'] == 1){
            $week_date = '周'.\app\admin\model\TeacherClassDtl::numberToChinese($weekday);
        }else{
            $week_date = $params['week_date'];
        }
        $params['week_date'] = $week_date;//日/周
        $count = TeacherSubscribe::where(['teacher_id'=>$class['teacher_id'],'week'=>$weekday])->where('class_id >0 and class_id !='.$class['id'])->count();
        if($count>0){
            $this->error('存在不可配置的可约时间');
        }

        $result = false;
        Db::startTrans();
        try {
            //是否采用模型验证
            if ($this->modelValidate) {
                $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
                $this->model->validateFailException()->validate($validate);
            }
            if(isset($class_num_alls)){
                \app\admin\model\TeacherClassDtl::jd_send_notice($params['teacher_class_id']);
                $class->save(['completed_class_num'=>$class_num_alls]);
            }
            $ts = [];
            $ts['teacher_id'] = $class['teacher_id'];
            $ts['week'] = $weekday;
            $ts['class_id'] = $params['teacher_class_id'];
            TeacherSubscribe::insert($ts);

            IdentityInfo::up_week($class['teacher_id']);
            $result = $this->model->allowField(true)->save($params);
            Db::commit();
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if ($result === false) {
            $this->error(__('No rows were inserted'));
        }

        $dtl = $this->model->where(['teacher_class_id'=>$params['teacher_class_id']])->select();

        $all_class_num = 0;
        foreach ($dtl as $k=>$v){
            $all_class_num = precisionRestore($v['class_num'],$all_class_num,'加法');
        }
        if($all_class_num>0){
            $class_num_all = (int)$class['class_num_all'];
            $all_class_num = (int)$all_class_num;
            if($all_class_num&&$class_num_all){
                $class_period = ceil($class_num_all / $all_class_num);
            }else{
                $class_period = '暂无计划';
            }
            TeacherClass::where(['id'=>$params['teacher_class_id']])->update(['class_period'=>$class_period]);
        }
        $this->success();
    }

    /**
     * 编辑
     *
     * @param $ids
     * @return string
     * @throws DbException
     * @throws \think\Exception
     */
    public function edit($ids = null)
    {
        $row = $this->model->get($ids);
        if (!$row) {
            $this->error(__('No Results were found'));
        }
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds) && !in_array($row[$this->dataLimitField], $adminIds)) {
            $this->error(__('You have no permission'));
        }
        if (false === $this->request->isPost()) {
            $params = $this->request->param();
            $class = TeacherClass::where(['id'=>$params['class_id']])->find();
//            if($class['status'] != 1){
//                $this->error('已完成或已中止的课程不可修改课程安排');
//            }

            if($row['cycle'] == 2){
                $inputDate = $row['week_date'];
                $weekday = date('N', strtotime($inputDate));
            }else{
                $identity_info = new IdentityInfo();
                $week_name = $identity_info->getWeekNameList();
                $weekday = $week_name[$row['week_date']];
            }
            $week_arr = TeacherSubscribe::where(['teacher_id'=>$class['teacher_id']])->where('1=1 and (class_id = 0 or (class_id = '.$params['class_id'].' and week = '.$weekday.'))')->column('week');
            $arr = [];
            foreach ($week_arr as $k=>$v){
                $arr[] = (int)$v;
            }
            sort($arr);
            $data['week'] = $arr;
            $identity_info_model = new \app\admin\model\IdentityInfo();
            $getWeekList = $identity_info_model->getWeekList();
            $week_name = [];
            foreach ($arr as $k=>$v){
                $week_name[$v] = $getWeekList[$v];
            }

            $this->view->assign("weekList", $week_name);
            $this->view->assign("weekday", $weekday);
            $this->view->assign("period_set", $class['period_set']);


            $this->view->assign('row', $row);
            return $this->view->fetch();
        }

        $params = $this->request->post('row/a');
        if (empty($params)) {
            $this->error(__('Parameter %s can not be empty', ''));
        }
        $params = $this->preExcludeFields($params);


        if(!isset($params['week_date'])||!$params['week_date']){
            $this->error('日/周必传');
        }
        $class = TeacherClass::where(['id'=>$params['teacher_class_id']])->find();
        $params['cycle'] = $class['period_set'];
        if($params['status'] == 2&&$row['status'] == 1){
            //未完成改为已完成的话 增加进度
            $class_num = $params['class_num'];
            $class_num_alls = precisionRestore($class_num,$class['completed_class_num'],'加法');
        }
        if($params['status'] == 1&&$row['status'] == 2){
            $class_num = $params['class_num'];
            $class_num_alls = precisionRestore($class['completed_class_num'],$class_num,'减法');
        }

        $ts = TeacherSubscribe::where(['teacher_id'=>$class['teacher_id']])->where('1=1 and (class_id = 0 or (class_id='.$params['teacher_class_id'].' and week = '.$params['week_date'].'))')->select();
        $week_arr = [];
        foreach ($ts as $k=>$v){
            $week_arr[] = $v['week'];
        }

        $identity_info = \app\admin\model\IdentityInfo::where(['user_id'=>$class['teacher_id'],'identity_type'=>'教师'])->with(['clubDtlS'])->find();
        if(!$identity_info){
            $this->error('教师不存在');
        }

        $td = \app\admin\model\TeacherDetail::where(['id'=>$class['teacher_detail_id']])->find();
        if(isset($td['course_duration'])&&$td['course_duration']){
            //当教师课程配置了课程时间 则赋值课程时间
            $duration = $td['course_duration'];
        }else{
            //如果没有配置，则取公共课程时间
            $defaultDuration = Config::get('course.default_course_duration', '');
            $duration = $defaultDuration;
        }
        $time = explode('-',$identity_info['appointment_time']);
        $ws_weekday = $weekday = $params['week_date'];//长期默认周 传过来的是数字
        //判断日期是否在可约范围内，判断上课时间，判断课时
        if($class['period_set'] == 2){
            //短期
            $inputDate = $params['week_date'];

            $ws_weekday = $weekday = date('N', strtotime($inputDate));
        }

        if (!in_array($weekday, $week_arr)) {
            $this->error('周'. \app\admin\model\TeacherClassDtl::numberToChinese($weekday).'不在可约时间');
        }
        if($params['class_num']>6){
            $this->error('单次上课最大6课时');
        }
        if(isset($time[0])&&$time[0]&&isset($time[1])&&$time[1]){
            $add_time = precisionRestore($params['class_num'],$duration,'乘法');
            $end_time = $this->safeTimeAdd($params['time_start'],$add_time);
            if(!$end_time){
                $this->error('课程开始时间加上课时不可跨天');
            }
            $result = $this->isTimeBetween($params['time_start'], $time[0], $time[1]);
            if($result == false){
                $this->error('课程开始时间不在服务时间内');
            }
            $result = $this->isTimeBetween($end_time, $time[0], $time[1]);
            if($result == false){
                $this->error('课程结束时间不在服务时间内');
            }
        }

        if($class['period_set'] == 1){
            $week_date = '周'.\app\admin\model\TeacherClassDtl::numberToChinese($weekday);
        }else{
            $week_date = $params['week_date'];
        }
        $params['week_date'] = $week_date;//日/周
        $count = TeacherSubscribe::where(['teacher_id'=>$class['teacher_id'],'week'=>$weekday])->where('class_id >0 and class_id !='.$class['id'])->count();
        if($count>0){
            $this->error('存在不可配置的可约时间');
        }

        $result = false;
        Db::startTrans();
        try {
            //是否采用模型验证
            if ($this->modelValidate) {
                $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
                $row->validateFailException()->validate($validate);
            }
            if(isset($class_num_alls)){
                \app\admin\model\TeacherClassDtl::jd_send_notice($params['teacher_class_id']);
                $class->save(['completed_class_num'=>$class_num_alls]);
            }

            if($row['cycle'] == 2){
                $inputDate = $row['week_date'];
                $weekday = date('N', strtotime($inputDate));
            }else{
                $identity_info = new IdentityInfo();
                $week_name = $identity_info->getWeekNameList();
                $weekday = $week_name[$row['week_date']];
            }

            $ts_where['teacher_id'] = $class['teacher_id'];
            $ts_where['week'] = $weekday;
            $ts_where['class_id'] = $class['id'];
            $ts['week'] = $ws_weekday;
            TeacherSubscribe::where($ts_where)->update($ts);

            IdentityInfo::up_week($class['teacher_id']);
            $result = $row->allowField(true)->save($params);
            Db::commit();
        } catch (ValidateException|PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if (false === $result) {
            $this->error(__('No rows were updated'));
        }

        $dtl = $this->model->where(['teacher_class_id'=>$params['teacher_class_id']])->select();

        $all_class_num = 0;
        foreach ($dtl as $k=>$v){
            $all_class_num = precisionRestore($v['class_num'],$all_class_num,'加法');
        }
        if($all_class_num>0){
            $class_num_all = (int)$class['class_num_all'];
            $all_class_num = (int)$all_class_num;
            if($all_class_num&&$class_num_all){
                $class_period = ceil($class_num_all / $all_class_num);
            }else{
                $class_period = '暂无计划';
            }
            TeacherClass::where(['id'=>$params['teacher_class_id']])->update(['class_period'=>$class_period]);
        }

        $this->success();
    }


    /**
     * 删除
     *
     * @param $ids
     * @return void
     * @throws DbException
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     */
    public function del($ids = null)
    {
        if (false === $this->request->isPost()) {
            $this->error(__("Invalid parameters"));
        }
        $ids = $ids ?: $this->request->post("ids");
        if (empty($ids)) {
            $this->error(__('Parameter %s can not be empty', 'ids'));
        }
        $pk = $this->model->getPk();
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds)) {
            $this->model->where($this->dataLimitField, 'in', $adminIds);
        }
        $list = $this->model->where($pk, 'in', $ids)->select();
        $identity_info_model = new IdentityInfo();
        $getWeekNameList = $identity_info_model->getWeekNameList();
        $week_arr = [];
        $class_id = 0;
        foreach ($list as $k=>$v){
            if($v['cycle'] == 1){
                //每周
                $weekday = isset($getWeekNameList[$v['week_date']]) ? $getWeekNameList[$v['week_date']] : '';
            }else{
                //日期
                $weekday = date('N', strtotime($v['week_date']));
            }
            $week_arr[] = $weekday;
            $class_id = $v['teacher_class_id'];
        }
        $class = TeacherClass::where(['id'=>$class_id])->find();
        if($class){
            TeacherSubscribe::where(['teacher_id'=>$class['teacher_id'],'class_id'=>$class_id])->whereIn('week',$week_arr)->update(['class_id'=>0]);
        }
        $count = 0;
        Db::startTrans();
        try {
            foreach ($list as $item) {
                $count += $item->delete();
            }
            Db::commit();
        } catch (PDOException|Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
        if ($count) {
            $this->success();
        }
        $this->error(__('No rows were deleted'));
    }



    function isTimeBetween($checkTime, $startTime, $endTime) {
        $checkTime = trim($checkTime);
        $startTime = trim($startTime);
        $endTime = trim($endTime);
        $check = \DateTime::createFromFormat('H:i', $checkTime);
        $start = \DateTime::createFromFormat('H:i', $startTime);
        $end = \DateTime::createFromFormat('H:i', $endTime);

        if ($check >= $start && $check <= $end) {
            return true;
        }
        return false;
    }

    /**
     * 安全时间加法（禁止跨天）
     * @param string $time 输入时间（格式: H:i）
     * @param int $minutes 要添加的分钟数（支持负数）
     * @return string|false 成功返回时间，失败返回false
     */
    function safeTimeAdd($time, $minutes) {
        $time = trim($time);
        $dt = \DateTime::createFromFormat('H:i', $time);
        if (!$dt) return false;

        $dt->add(new \DateInterval('PT' . abs($minutes) . 'M'));
        if ($minutes < 0) {
            $dt->sub(new \DateInterval('PT' . abs($minutes) . 'M'));
        }

        $originalDay = \DateTime::createFromFormat('H:i', $time)->format('Y-m-d');
        return ($dt->format('Y-m-d') === $originalDay)
            ? $dt->format('H:i')
            : false;
    }
}
